SSH Key Login Only
SSH key login only means configuring OpenSSH so that users can authenticate using public key cryptography and cannot authenticate using passwords or interactive challenge methods. This is one of the most effective SSH hardening steps because it removes an entire class of brute-force and credential-stuffing attacks against password authentication.
Background and history
SSH originally supported password authentication for convenience, but internet-exposed servers quickly became targets for automated brute-force attempts. Key-based authentication became the standard secure approach because it relies on cryptographic proof instead of a shared secret typed over a network session. Modern hardening baselines typically disable password authentication entirely and rely on key pairs managed by administrators.
Adoption and where it’s commonly used
Common in:
- VPS and cloud servers with public SSH access
- Production web servers (WordPress stacks) where SSH is a high-value target
- Environments using configuration management and CI/CD (deploy keys, forced commands)
- Bastion host patterns where access is tightly controlled
Maintained by
- Maintained by the OpenSSH project community.
Best when to use
- The server is reachable from the internet and receives frequent SSH scans.
- You have reliable key management for all administrators.
- You want to eliminate password brute-force risk entirely.
- You plan to disable root SSH login and rely on sudo-capable admin users.
Not suitable when
- You cannot ensure every admin has working keys and a recovery path.
- You depend on password-based automation or legacy tooling that cannot use keys.
- You do not have console/serial access for recovery and cannot risk lockout.
Compatibility notes
-
Settings are in
/etc/ssh/sshd_configor/etc/ssh/sshd_config.d/*.confdepending on distro. -
System service name differs:
- Debian/Ubuntu:
ssh - RHEL-based:
sshd
- Debian/Ubuntu:
-
Some systems use additional auth mechanisms (PAM, keyboard-interactive). Disabling passwords alone may not fully disable interactive authentication unless you disable keyboard-interactive as well.
-
Ensure your firewall allows your SSH port before making changes.
Do not disable password authentication until you have confirmed that key-based login works in a separate SSH session for at least one sudo-capable user. Keep your original session open until verification is complete.
Concepts and how it works
- Your workstation holds a private key (keep it secret).
- The server stores your public key in
~/.ssh/authorized_keys. - During login, the server verifies you control the private key without sending it over the network.
Prerequisites
- An existing SSH session to the server
- A sudo-capable non-root user (recommended)
- Provider console/serial access or another recovery path
OpenSSHserver installed and running
Step 1: Create an SSH key on your workstation
Choose one of these key types. Ed25519 is recommended on modern systems.
Generate an Ed25519 key (recommended)
ssh-keygen -t ed25519 -a 64 -f ~/.ssh/id_ed25519
Generate an RSA key (legacy compatibility)
Use RSA only when Ed25519 is not supported by your environment.
ssh-keygen -t rsa -b 4096 -a 64 -f ~/.ssh/id_rsa
Use a passphrase for your private key on laptops and developer machines. It reduces impact if the key file is copied. For automation keys, use restricted accounts and narrow permissions.
Step 2: Install the public key on the server
Option A: Use ssh-copy-id (recommended)
Default port:
ssh-copy-id user@your_server_ip
Custom SSH port:
ssh-copy-id -p 2581 user@your_server_ip
Option B: Manual install (works everywhere)
On your workstation, print the public key:
cat ~/.ssh/id_ed25519.pub
On the server, as the target user:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
Paste the public key on its own line into authorized_keys.
Verify permissions:
ls -ld ~/.ssh
ls -l ~/.ssh/authorized_keys
Step 3: Test key-based login before changing the server
From your workstation, open a new terminal and test:
Default port:
ssh user@your_server_ip
Custom port:
ssh -p 2581 user@your_server_ip
Force key use (debug-friendly):
ssh -i ~/.ssh/id_ed25519 -p 2581 user@your_server_ip
If it fails, use verbose mode:
ssh -vvv -p 2581 user@your_server_ip
Step 4: Configure OpenSSH to allow keys and disable passwords
Prefer using drop-in configs when supported.
Create a hardening drop-in
Create /etc/ssh/sshd_config.d/10-key-auth.conf:
sudo tee /etc/ssh/sshd_config.d/10-key-auth.conf >/dev/null <<'EOF'
# Key-based authentication only
PubkeyAuthentication yes
# Disable password and interactive auth
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
# Optional: reduce auth noise
MaxAuthTries 3
LoginGraceTime 30
EOF
If your system does not use sshd_config.d, edit /etc/ssh/sshd_config directly and place the same directives near the end of the file.
ChallengeResponseAuthentication compatibilitySome OpenSSH versions ignore ChallengeResponseAuthentication in favor of KbdInteractiveAuthentication. Setting both is safe and reduces ambiguity across distributions.
Step 5: Validate configuration and reload SSH safely
Validate config syntax:
sudo sshd -t
If the command returns no output, syntax validation passed.
Reload the SSH daemon (preferred over restart):
sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd
Keep your original SSH session open.
Step 6: Confirm password authentication is disabled
Open a second session and verify:
- key login still works
- password login fails
Confirm key login works
ssh -p 2581 user@your_server_ip
Confirm passwords are rejected
From a different machine without your key, or by forcing password auth attempt:
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no -p 2581 user@your_server_ip
Expected: authentication fails.
Optional: Harden allowed users and root login
Key-only is strongest when paired with reduced login surface.
Restrict which users can SSH
Create /etc/ssh/sshd_config.d/20-allow-users.conf:
sudo tee /etc/ssh/sshd_config.d/20-allow-users.conf >/dev/null <<'EOF'
AllowUsers adminuser opsuser
EOF
Disable root SSH login
Create /etc/ssh/sshd_config.d/30-no-root.conf:
sudo tee /etc/ssh/sshd_config.d/30-no-root.conf >/dev/null <<'EOF'
PermitRootLogin no
EOF
Validate and reload:
sudo sshd -t
sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd
Troubleshooting
Key login fails after disabling passwords
Common causes:
- Wrong file permissions on
~/.sshorauthorized_keys - Wrong username or connecting to the wrong host/port
AllowUsers/AllowGroupsexcludes the user- Wrong key used by client (multiple keys loaded)
Server-side checks:
sudo ls -ld /home/<user> /home/<user>/.ssh 2>/dev/null || true
sudo ls -l /home/<user>/.ssh/authorized_keys 2>/dev/null || true
sudo sshd -T | grep -E '^(pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin|allowusers|allowgroups)'
Client-side checks:
ssh -vvv -p 2581 user@your_server_ip
ssh-add -l 2>/dev/null || true
SSH reload fails
sudo sshd -t
sudo journalctl -u ssh -n 200 --no-pager 2>/dev/null || sudo journalctl -u sshd -n 200 --no-pager
Locked out
Recovery requires provider console/serial access. Revert the last change:
- remove or edit the drop-in file(s)
- validate with
sshd -t - reload the service
Example revert:
sudo rm -f /etc/ssh/sshd_config.d/10-key-auth.conf
sudo sshd -t
sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd
Before applying SSH authentication changes on a remote VPS, ensure you can access a provider console session to revert changes if needed.
Security notes
- Store private keys securely and avoid copying them to servers.
- Use separate keys per administrator for accountability.
- Remove keys immediately when an operator leaves.
- For automation, prefer restricted keys (
command=,from=, no-pty) and dedicated accounts.
Example of a restricted key entry (advanced):
from="203.0.113.10",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,command="/usr/local/bin/deploy.sh" ssh-ed25519 AAAA... comment
Quick reference
| Goal | Command |
|---|---|
| - | |
| Generate key (Ed25519) | ssh-keygen -t ed25519 -a 64 |
| Copy key to server | ssh-copy-id -p 2581 user@host |
| Test key login | ssh -p 2581 user@host |
| Validate sshd config | sudo sshd -t |
| Reload sshd | sudo systemctl reload ssh || sudo systemctl reload sshd |
| Force password attempt (should fail) | ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no user@host |